<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>arguments</title>
  </head>
  <body>
    <script>
      //   "use strict";
      function func1(a, b, c) {
        console.log(arguments[0]);
        // Expected output: 1

        console.log(arguments[1]);
        // Expected output: 2

        console.log(arguments[2]);
        // Expected output: 3
      }

      //   func1(1, 2, 3);
      /**
       * arguments对象不是一个 Array 。
       * 它类似于Array，但除了 length 属性和索引元素之外没有任何Array属性。例如，它没有 pop 方法。但是它可以被转换为一个真正的Array：
       */
      function test(a, b) {
        // 转换为一个真正的Array
        // var args1 = Array.prototype.slice.call(arguments);
        // var args2 = [].slice.call(arguments);
        // console.log(args1);
        // console.log(args2);

        // // ES2015 转换为一个真正的Array
        // const args3 = Array.from(arguments);
        // const args4 = [...arguments];
        // console.log(args3);
        // console.log(args4);

        console.log(a, Object.prototype.toString.call(arguments));
        console.log(arguments[0], arguments[1]);
        console.log(typeof arguments[0]);
      }
      console.log(test.length); // 2

      test(1, 2, 3);

      // 定义连接字符串的函数
      function myConcat(separator) {
        var args = Array.prototype.slice.call(arguments, 1);
        return args.join(separator);
      }
      // returns "red, orange, blue"
      console.log(myConcat(", ", "red", "orange", "blue"));

      // 定义创建 HTML 列表的方法
      function list(type) {
        var result = "<" + type + "l><li>";
        var args = Array.prototype.slice.call(arguments, 1);
        result += args.join("</li><li>");
        result += "</li></" + type + "l>"; // end list

        return result;
      }
      var listHTML = list("u", "One", "Two", "Three");
      console.log(listHTML);

      // 剩余参数、默认参数和解构赋值参数
      function foo(...args) {
        return args;
      }
      console.log(foo(1, 2, 3)); // [1,2,3]

      function func(a) {
        arguments[0] = 99; // 更新了 arguments[0] 同样更新了 a
        console.log(a);
      }
      func(10); // 非严格模式 99 严格模式10

      // 非严格模式
      // 1函数入参没有包含剩余参数、默认参数和解构赋值
      function func2(a) {
        arguments[0] = 99; // 更新了 arguments[0] 同样更新了 a
        console.log(a);
      }
      func2(10);
      // 2.1函数入参有包含默认参数
      function func21(a = 40) {
        arguments[0] = 99; // 更新了 arguments[0] 不更新a
        console.log(a);
      }
      func21(10);
      // 2.2函数入参有包含剩余参数
      function func22(a, ...args) {
        arguments[0] = 99; // 更新了 arguments[0] 不更新a
        console.log(a);
      }
      func22(10);
      // 2.3函数入参有包含解构赋值
      function func23(a, { b, c }) {
        arguments[0] = 99; // 更新了 arguments[0] 不更新a
        console.log(a);
      }
      func23(10, {});
    </script>
  </body>
</html>
